
`include "axi_slave.sv";                                     
module axi_slave_top (
  
  aclk_i,
  areset_n_i,
  
  awid_i,
  awaddr_i,
  awlen_i,
  awsize_i,
  awburst_i,
  awvalid_i,
  awlock_i,
  awcache_i,
  awprot_i,
  awready_o,
  
  wid_i,
  wdata_i,
  wstrb_i,
  wlast_i,
  wvalid_i,
  wready_o,
  
  bid_o,
  bresp_o,
  bvalid_o,
  bready_i,
  
  arid_i,
  araddr_i,
  arlen_i,
  arsize_i,
  arburst_i,
  arvalid_i,
  arready_o,
  
  rid_o,
  rdata_o,
  rresp_o,
  rlast_o,
  rvalid_o,
  rready_i  
);


input           aclk_i;
input           areset_n_i;

input [3:0]     awid_i;
input [31:0]    awaddr_i;
input [3:0]     awlen_i;
input [2:0]     awsize_i;
input [1:0]     awburst_i;                                
input           awvalid_i;
input [1:0]     awlock_i;
input [3:0]     awcache_i;
input [2:0]     awprot_i;
output          awready_o;

input [3:0]     wid_i;
input [127:0]   wdata_i;
input [3:0]     wstrb_i;
input           wlast_i;
input           wvalid_i;
output          wready_o;

output [3:0]    bid_o;
output [1:0]    bresp_o;
output          bvalid_o;
input           bready_i;

input [3:0]     arid_i;
input [31:0]    araddr_i;
input [3:0]     arlen_i;
input [2:0]     arsize_i;
input [1:0]     arburst_i;
input           arvalid_i;
output          arready_o;
output [3:0]    rid_o;
output [127:0]   rdata_o;
output [1:0]    rresp_o;
output          rlast_o;
output          rvalid_o;
input           rready_i;



wire   [31:0]   reg_rd_addr_o;
reg  [127:0]   reg_rd_data_i;
wire            reg_rd_enab_o;
reg             reg_rd_err_i   = 1'b0;
reg             reg_rd_datav_i;

wire   [31:0]   reg_wr_addr_o;
wire   [127:0]  reg_wr_data_o;
wire            reg_wr_datav_o;
reg             reg_wr_err_i   = 1'b0;
reg             reg_wr_done_i;
  
  reg    [127:0]  reg_data_array[31:0];
  reg      [3:0]  wr_req_cnt;

axi_slave  axi_slave_i(
	
	.aclk_i                        (aclk_i),
	.areset_n_i                    (areset_n_i),
          
	.awid_i                        (awid_i[3:0]),
	.awaddr_i                      (awaddr_i[31:0]),
	.awlen_i                       (awlen_i[3:0]),
	.awsize_i                      (awsize_i[2:0]),
	.awburst_i                     (awburst_i[1:0]),
	.awvalid_i                     (awvalid_i),
	.awlock_i                      (awlock_i[1:0]),
	.awcache_i                     (awcache_i[3:0]),
	.awprot_i                      (awprot_i[2:0]),
	.awready_o                     (awready_o),
            
	.wid_i                         (wid_i[3:0]),
	.wdata_i                       (wdata_i[127:0]),
	.wstrb_i                       (wstrb_i[3:0]),
	.wlast_i                       (wlast_i),
	.wvalid_i                      (wvalid_i),
	.wready_o                      (wready_o),
         
	.bid_o                         (bid_o[3:0]),
	.bresp_o                       (bresp_o[1:0]),
	.bvalid_o                      (bvalid_o),
	.bready_i                      (bready_i),
                            
	.arid_i                        (arid_i[3:0]),
	.araddr_i                      (araddr_i[31:0]),
	.arlen_i                       (arlen_i[3:0]),
	.arsize_i                      (arsize_i[2:0]),
	.arburst_i                     (arburst_i[1:0]),
	.arvalid_i                     (arvalid_i),
	.arready_o                     (arready_o),
	.rid_o                         (rid_o[3:0]),
	.rdata_o                       (rdata_o[127:0]),
	.rresp_o                       (rresp_o[1:0]),
	.rlast_o                       (rlast_o),
	.rvalid_o                      (rvalid_o),
	.rready_i                      (rready_i),
               
	.reg_rd_addr_o                 (reg_rd_addr_o[31:0]),
	.reg_rd_data_i                 (reg_rd_data_i[127:0]),
	.reg_rd_enab_o                 (reg_rd_enab_o),
	.reg_rd_err_i                  (reg_rd_err_i),
	.reg_rd_datav_i                (reg_rd_datav_i),
	.reg_wr_addr_o                 (reg_wr_addr_o[31:0]),
	.reg_wr_data_o                 (reg_wr_data_o[127:0]),
	.reg_wr_datav_o                (reg_wr_datav_o),
	.reg_wr_err_i                  (reg_wr_err_i),
	.reg_wr_done_i                 (reg_wr_done_i)
	);
	


  always @ (posedge aclk_i or negedge areset_n_i)
	begin
	  if (!areset_n_i)
		begin
		  reg_rd_datav_i         <= 1'b0;
		  reg_wr_done_i          <= 1'b0;
          wr_req_cnt[3:0]        <= 4'b0;
		end
      else
		begin
		  
		  if (reg_rd_datav_i)
			begin
			  reg_rd_datav_i    <= 1'b0;
			end
		  else if (reg_rd_enab_o)
			begin
               reg_rd_datav_i    <= 1'b1;
              reg_rd_data_i[127:0] <= reg_data_array[reg_rd_addr_o[31:0]][127:0];
			end
		  
		  if (reg_wr_done_i)
			begin
			  reg_wr_done_i     <= 1'b0;
              wr_req_cnt[3:0]   <= 4'd0;
			end
		  else if (reg_wr_datav_o)
			begin
              
              if (wr_req_cnt[3:0] == awlen_i[3:0])
                begin
                  reg_wr_done_i    <= 1'b1;
                end
              wr_req_cnt[3:0]   <= wr_req_cnt[3:0] + 4'd1; 
              reg_data_array[reg_wr_addr_o[31:0]][127:0]  <= reg_wr_data_o[127:0];
			end
		end
	end
 

endmodule




	
	
